home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung 2 / Power-Programmierung CD 2 (Tewi)(1994).iso / gnu / gnulib / sipp / libsipp / ellipsoi.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-03  |  9.9 KB  |  265 lines

  1. /**
  2.  ** sipp - SImple Polygon Processor
  3.  **
  4.  **  A general 3d graphic package
  5.  **
  6.  **  Copyright Equivalent Software HB  1992
  7.  **
  8.  ** This program is free software; you can redistribute it and/or modify
  9.  ** it under the terms of the GNU General Public License as published by
  10.  ** the Free Software Foundation; either version 1, or any later version.
  11.  ** This program is distributed in the hope that it will be useful,
  12.  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  ** GNU General Public License for more details.
  15.  ** You can receive a copy of the GNU General Public License from the
  16.  ** Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  **/
  18.  
  19. /**
  20.  ** ellipsoid.c - Creating ellipsiods and spheres as sipp objects.
  21.  **/
  22.  
  23. #include <xalloca.h>
  24. #include <math.h>
  25.  
  26. #include <sipp.h>
  27. #include <primitives.h>
  28.  
  29.  
  30. Object *
  31. sipp_ellipsoid(x_rad, y_rad, z_rad, res, surface, shader, texture)
  32.     double  x_rad;
  33.     double  y_rad;
  34.     double  z_rad;
  35.     int     res;
  36.     void   *surface;
  37.     Shader *shader;
  38.     int     texture;
  39. {
  40.     int      i, j;
  41.     double   factor;
  42.     double   factor1;
  43.     double   factor2;
  44.     double   zradprim;
  45.     double   zradprim1;
  46.     double   zradprim2;
  47.     double  *x_arr;
  48.     double  *y_arr;
  49.     double  *u_arr;
  50.     double  *v1, *v2;
  51.     Object  *ellipsoid;
  52.     
  53.     /* Odd resolutions make ugly spheres since the poles will be */
  54.     /* different in size. */
  55.     if (res & 1) {
  56.         res++;
  57.     }
  58.  
  59.     /* Create two arrays with the coordinates of the points */
  60.     /* around the perimeter at Z = 0 */
  61.     x_arr = (double *) alloca((res + 1) * sizeof(double));
  62.     y_arr = (double *) alloca((res + 1) * sizeof(double));
  63.     u_arr = (double *) alloca((res + 1) * sizeof(double));
  64.     if (texture == SPHERICAL || texture == NATURAL) {
  65.         v1    = (double *) alloca((res + 1) * sizeof(double));
  66.         v2    = (double *) alloca((res + 1) * sizeof(double));
  67.     }
  68.     for (i = 0; i <= res; i++) {
  69.         x_arr[i] = x_rad * cos(i * 2.0 * M_PI / res);
  70.         y_arr[i] = y_rad * sin(i * 2.0 * M_PI / res);
  71.         u_arr[i] = (double)i / (double)res;
  72.     }
  73.  
  74.     /* Create the top pole */
  75.     factor = sin(2.0 * M_PI / res);
  76.     zradprim = z_rad * cos(2.0 * M_PI / res);
  77.     if (texture == SPHERICAL || texture == NATURAL) {
  78.         for (i = 0; i < res; i++) {
  79.             v2[i] = (atan(zradprim 
  80.                           / sqrt(factor * factor * (x_arr[i] * x_arr[i] 
  81.                                                     + y_arr[i] * y_arr[i])))
  82.                      / M_PI + 0.5);
  83.         }
  84.         v2[i] = v2[0];
  85.     }
  86.     for (i = 0; i < res; i++) {
  87.         switch (texture) {
  88.           case NATURAL:
  89.           case SPHERICAL:
  90.             vertex_tx_push(x_arr[i] * factor, y_arr[i] * factor, zradprim, 
  91.                            u_arr[i], v2[i], 0.0);
  92.             vertex_tx_push(factor * x_arr[i + 1], factor * y_arr[i + 1],
  93.                            zradprim, 
  94.                            u_arr[i + 1], v2[i + 1], 0.0);
  95.             vertex_tx_push(0.0, 0.0, z_rad, u_arr[i + 1], 1.0, 0.0);
  96.             vertex_tx_push(0.0, 0.0, z_rad, u_arr[i], 1.0, 0.0);
  97.             break;
  98.  
  99.           case CYLINDRICAL:
  100.             vertex_tx_push(x_arr[i] * factor, y_arr[i] * factor, zradprim, 
  101.                            u_arr[i], zradprim / (2.0 * z_rad) + 0.5, 0.0);
  102.             vertex_tx_push(factor * x_arr[i + 1], factor * y_arr[i + 1],
  103.                            zradprim, 
  104.                            u_arr[i + 1], zradprim / (2.0 * z_rad) + 0.5, 0.0);
  105.             vertex_tx_push(0.0, 0.0, z_rad, u_arr[i + 1], 1.0, 0.0);
  106.             vertex_tx_push(0.0, 0.0, z_rad, u_arr[i], 1.0, 0.0);
  107.             break;
  108.  
  109.           case WORLD:
  110.           default:
  111.             vertex_tx_push(x_arr[i] * factor, y_arr[i] * factor, zradprim, 
  112.                            x_arr[i] * factor, y_arr[i] * factor, zradprim);
  113.             vertex_tx_push(factor * x_arr[i + 1],
  114.                            factor * y_arr[i + 1],
  115.                            zradprim, 
  116.                            factor * x_arr[i + 1],
  117.                            factor * y_arr[i + 1],
  118.                            zradprim);
  119.             vertex_tx_push(0.0, 0.0, z_rad, 0.0, 0.0, z_rad);
  120.             break;
  121.         }
  122.         polygon_push();
  123.     }
  124.  
  125.     /* Create the surface between the poles. */
  126.     factor2 = factor;
  127.     zradprim2 = zradprim;
  128.     for (j = 1; j < res / 2 - 1; j++) {
  129.         factor1 = factor2;
  130.         factor2 = sin((j + 1) * M_PI / (res / 2));
  131.         zradprim1 = zradprim2;
  132.         zradprim2 = z_rad * cos((j + 1) * M_PI / (res / 2));
  133.         if (texture == SPHERICAL || texture == NATURAL) {
  134.             v1 = v2;
  135.             for (i = 0; i < res; i++) {
  136.                 v2[i] = (atan(zradprim2
  137.                               / sqrt(factor2 * factor2 
  138.                                      * (x_arr[i] * x_arr[i] 
  139.                                         + y_arr[i] * y_arr[i])))
  140.                          / M_PI + 0.5);
  141.             }
  142.             v2[i] = v2[0];
  143.         }
  144.  
  145.         for (i = 0; i < res; i++) {
  146.             switch (texture) {
  147.               case NATURAL:
  148.               case SPHERICAL:
  149.                 vertex_tx_push(factor1 * x_arr[i], factor1 * y_arr[i], 
  150.                                zradprim1, 
  151.                                u_arr[i], v1[i], 0.0);
  152.                 vertex_tx_push(factor2 * x_arr[i], factor2 * y_arr[i], 
  153.                                zradprim2, 
  154.                                u_arr[i], v2[i], 0.0);
  155.                 vertex_tx_push(factor2 * x_arr[i + 1], factor2 * y_arr[i + 1],
  156.                                zradprim2, 
  157.                                u_arr[i + 1], v2[i + 1], 0.0);
  158.                 vertex_tx_push(factor1 * x_arr[i + 1], factor1 * y_arr[i + 1],
  159.                                zradprim1, 
  160.                                u_arr[i + 1], v1[i + 1], 0.0);
  161.                 break;
  162.  
  163.               case CYLINDRICAL:
  164.                 vertex_tx_push(factor1 * x_arr[i], factor1 * y_arr[i], 
  165.                                zradprim1, 
  166.                                u_arr[i], zradprim1 / (2.0 * z_rad) + 0.5, 0.0);
  167.                 vertex_tx_push(factor2 * x_arr[i], factor2 * y_arr[i], 
  168.                                zradprim2, 
  169.                                u_arr[i], zradprim2 / (2.0 * z_rad) + 0.5, 0.0);
  170.                 vertex_tx_push(factor2 * x_arr[i + 1], factor2 * y_arr[i + 1],
  171.                                zradprim2, 
  172.                                u_arr[i + 1], zradprim2 / (2.0 * z_rad) + 0.5, 
  173.                                0.0);
  174.                 vertex_tx_push(factor1 * x_arr[i + 1], factor1 * y_arr[i + 1],
  175.                                zradprim1, 
  176.                                u_arr[i + 1], zradprim1 / (2.0 * z_rad) + 0.5, 
  177.                                0.0);
  178.                 break;
  179.  
  180.               case WORLD:
  181.               default:
  182.                 vertex_tx_push(factor1 * x_arr[i], factor1 * y_arr[i], 
  183.                                zradprim1, 
  184.                                factor1 * x_arr[i], factor1 * y_arr[i], 
  185.                                zradprim1);
  186.                 vertex_tx_push(factor2 * x_arr[i], factor2 * y_arr[i], 
  187.                                zradprim2, 
  188.                                factor2 * x_arr[i], factor2 * y_arr[i], 
  189.                                zradprim2);
  190.                 vertex_tx_push(factor2 * x_arr[i + 1], factor2 * y_arr[i + 1],
  191.                                zradprim2, 
  192.                                factor2 * x_arr[i + 1], factor2 * y_arr[i + 1],
  193.                                zradprim2);
  194.                 vertex_tx_push(factor1 * x_arr[i + 1], factor1 * y_arr[i + 1],
  195.                                zradprim1, 
  196.                                factor1 * x_arr[i + 1], factor1 * y_arr[i + 1],
  197.                                zradprim1);
  198.             }
  199.             polygon_push();
  200.         }
  201.     }
  202.  
  203.     /* Create the bottom pole */
  204.     factor = sin(2.0 * M_PI / res);
  205.     zradprim = -z_rad * cos(2.0 * M_PI / res);
  206.     for (i = 0; i < res; i++) {
  207.         switch (texture) {
  208.           case NATURAL:
  209.           case SPHERICAL:
  210.             vertex_tx_push(factor * x_arr[i + 1], factor * y_arr[i + 1],
  211.                            zradprim, 
  212.                            u_arr[i + 1], v2[i + 1], 0.0);
  213.             vertex_tx_push(x_arr[i] * factor, y_arr[i] * factor, zradprim, 
  214.                            u_arr[i], v2[i], 0.0);
  215.             vertex_tx_push(0.0, 0.0, -z_rad, 
  216.                            u_arr[i], 0.0, 0.0);
  217.             vertex_tx_push(0.0, 0.0, -z_rad, 
  218.                            u_arr[i + 1], 0.0, 0.0);
  219.             break;
  220.  
  221.           case CYLINDRICAL:
  222.             vertex_tx_push(factor * x_arr[i + 1], factor * y_arr[i + 1],
  223.                            zradprim, 
  224.                            u_arr[i + 1], zradprim / (2.0 * z_rad) + 0.5, 0.0);
  225.             vertex_tx_push(x_arr[i] * factor, y_arr[i] * factor, zradprim, 
  226.                            u_arr[i], zradprim / (2.0 * z_rad) + 0.5, 0.0);
  227.             vertex_tx_push(0.0, 0.0, -z_rad, 
  228.                            u_arr[i], 0.0, 0.0);
  229.             vertex_tx_push(0.0, 0.0, -z_rad, 
  230.                            u_arr[i + 1], 0.0, 0.0);
  231.             break;
  232.  
  233.           case WORLD:
  234.           default:
  235.             vertex_tx_push(x_arr[i + 1] * factor, y_arr[i + 1] * factor,
  236.                            zradprim, 
  237.                            x_arr[i + 1] * factor, y_arr[i + 1] * factor,
  238.                            zradprim);
  239.             vertex_tx_push(x_arr[i] * factor, y_arr[i] * factor, zradprim, 
  240.                            x_arr[i] * factor, y_arr[i] * factor, zradprim);
  241.             vertex_tx_push(0.0, 0.0, -z_rad, 0.0, 0.0, -z_rad);
  242.             break;
  243.         }
  244.         polygon_push();
  245.     }
  246.  
  247.     ellipsoid = object_create();
  248.     object_add_surface(ellipsoid, surface_create(surface, shader));
  249.  
  250.     return ellipsoid;
  251. }
  252.  
  253.  
  254. Object *
  255. sipp_sphere(radius, res, surface, shader, texture)
  256.     double  radius;
  257.     int     res;
  258.     void   *surface;
  259.     Shader *shader;
  260.     int     texture;
  261. {
  262.     return sipp_ellipsoid(radius, radius, radius, res, surface, shader,
  263.                           texture);
  264. }
  265.